<?php
/**
 * Created by PhpStorm.
 * User: admin
 * Date: 2019/10/21
 * Time: 16:31
 */

namespace app\adminapiv3\service;

use app\adminapiv3\service\permissionsManage\PermissionsService;
use app\common\model\Ip;
use think\Db;

class Login extends Base
{

    private $toekn;
    private $loginIp;
    private $loginTime;
    private $year;
    private $month;
    private $day;
    private $loginUser;
    private $maxKeepLoginFailedCount = 5;
    private $stopLoginTime = 86400;
    private $failed = 1;
    private $nowFailedCount = 0;

    function __construct($real_name)
    {
        $this->loginUser = db('ServerUser')->alias('su')
            ->join('ServerUserGroup sug', 'sug.id= su.user_group_id')
            ->field('su.id,su.real_name,su.password,su.show_name,su.user_group_id,sug.level user_group_level')
            ->where('real_name', $real_name)
            ->find();

        $loginFailConfFile = './config/login.conf';
        if(file_exists($loginFailConfFile))
        {
            $loginFailConf = file_get_contents($loginFailConfFile);
            $loginFailSetting = json_decode($loginFailConf, true);
            $this->maxKeepLoginFailedCount = $loginFailSetting['fail_count'];
            $this->stopLoginTime = $loginFailSetting['fail_time'];
        }
        
        $this->loginIp = $_SERVER['REMOTE_ADDR'];
        $this->loginTime = time();
        $this->year = date('Y', $this->loginTime);
        $this->month = date('m', $this->loginTime);
        $this->day = date('d', $this->loginTime);
    }
    /**
     * @name 登录
     * @param $name
     * @param $password
     * @param $captchaCode
     * @author wx
     * @date 2019/10/21 16:32
     */
    function login($password, $captchaCode)
    {

        //2. 验证码验证
        if(!$this->checkCaptcha($captchaCode))
        {
            $this->setError($this->CODE_FAIL, '验证码输入错误');
            return [];
        }

        if(!$this->checkIp($captchaCode))
        {
            $this->setError($this->CODE_FAIL, '非法登录系统');
            return [];
        }

        if(empty($this->loginUser))
        {
            $this->setError($this->CODE_FAIL, '用户名或密码输入错误');
            return [];
        }

        if(!$this->checkErrorLogin())
        {
            $failTime = $this->stopLoginTime / 3600;

            if($failTime < 1){
                $failTime = $failTime * 60 .'分钟';
            }else{
                $failTime = $failTime .'小时';
            }
            $this->setError($this->CODE_FAIL, '今日登录失败超过'.$this->maxKeepLoginFailedCount.'次，请于'.$failTime.'后再试!');
            return [];
        }



        //5. 验证密码
        if(!$this->checkPassword($password))
        {
            $this->setError($this->CODE_FAIL, '用户名或密码输入错误');
            return [];
        }


        //6. 登录成功,返回数据
        return $this->returnData();
    }

    /**
     * @name ip白名单验证
     * @author wx
     * @date 2019/10/21 16:37
     */
    function checkIp()
    {
        //1. 验证是否需要验证ip
        $fileName = '../runtime/config/allow_ip.conf';

        if (file_exists($fileName)) {
            $allowConfig = file_get_contents($fileName);
            $allowArr = json_decode($allowConfig, true);

            if($allowArr['status'] == 1){//1为开启ip白名单自动加入,0为手动

                $timeRangeArr = array(
                    0 => 0,
                    1 => 1800,
                    2 => 3600,
                    3 => 8*3600,
                    4 => 16*3600,
                );

                $nowTime = time();
                $time = $timeRangeArr[$allowArr['time_range']];

                if($time == 0 || $nowTime <= $allowArr['start_time'] + $time){//不验证白名单
                    //添加当前ip到ip白名单中
                    $ipInfo = db('server_allow_ip')->where('ip', $this->loginIp)->count();
                    if(!$ipInfo){
                        $addData['ip'] = $_SERVER['REMOTE_ADDR'];
                        $addData['ctime'] = time();
                        $addData['login_time'] = time();

                        db('server_allow_ip')->insert($addData);

                        return true;
                    }
                }
            }
        }

        //2. 验证ip
        $ipInfo = db('server_allow_ip')->where('ip', $this->loginIp)->count();

        if(!$ipInfo){
            $this->setError($this->CODE_FAIL, '非法登录系统');
            return false;
        }

        return true;
    }

    /**
     * @name 验证验证码
     * @param $captchaCode
     * @return bool
     * @author wx
     * @date 2019/10/22 11:24
     */
    function checkCaptcha($captchaCode)
    {
        
        if(db('ServerRandCode')->where('ip', $this->loginIp)->where('code', $captchaCode)->where('ctime', '<', time()+60)->count()){
            return true;
        }
        return false;
        
    }



    /**
     * @name 检查用户登录错误次数
     * @param $userInfo
     * @return bool
     * @author wx
     * @date 2019/11/27 13:23
     */
    function checkErrorLogin()
    {

        //查询今日最早登录错误的时间
        $log = db('ServerLoginLog')->where('user_id', $this->loginUser['id'])
        ->field('login_time,failed')
        ->where('login_ip', $this->loginIp)
        ->where('year', $this->year)
        ->where('month', $this->month)
        ->where('day', $this->day)
        ->order('login_time', 'DESC')
        ->limit($this->maxKeepLoginFailedCount)
        ->select();



        if (empty($log)) {//今日没有登录
            return true;
        }

        $loginFailed = 0;
        foreach($log as $value)
        {
            $loginFailed += $value['failed'];
        }

        $this->nowFailedCount = $loginFailed;

        $last_login = array_pop($log);


        if (($loginFailed >= $this->maxKeepLoginFailedCount) && ($last_login['login_time'] + $this->stopLoginTime >= $this->loginTime)) {
            return false;
        }

        return true;
    }

    /**
     * @name 验证密码
     * @param $password
     * @Author wx
     * @date 2019/4/19 15:46
     */
    public function checkPassword($password)
    {
        //更新ip白名单的登录时间
        db('server_allow_ip')->where(['ip' => $_SERVER['REMOTE_ADDR']])->update(['login_time' => time()]);

        $serverPassword = new Password();

        if(!$serverPassword->decrypt($password, $this->loginUser['password'])){
            return false;
        }

        db('ServerUser')->where('id', $this->loginUser['id'])->update([
            'last_login_time' => $this->loginTime,
            'last_login_ip' => $this->loginIp,
            'token' => $this->createToken($this->loginUser),
        ]);

        return true;
    }

    /**
     * @name: 生成 登录凭证
     * @Param: 
     * @Description: 
     * @Author: foo
     * @Date: 2020-05-27 22:56:12
     */
    private function createToken ($userInfo)
    {
        $data = array(
            'user_real_name' => $userInfo['real_name'],
            'user_id' => $userInfo['id'],
            'user_group_id' => $userInfo['user_group_id'],
            'login_ip' => $_SERVER['REMOTE_ADDR'],
            'eTime' => time(),
        );
        $dataJson = json_encode($data);

        $this->toekn = $return = md5($dataJson);

        return $return;
    }
    /**
     * @name: 返回数据
     * @Param: 
     * @Description: 
     * @Author: foo
     * @Date: 2020-05-27 15:10:38
     */
    function returnData()
    {
        $this->failed = 0;

        //1. 查看授权状态
        $systemAuthServer = new ServerAuth();
        $authStatus = $systemAuthServer->expireDay($this->loginUser['user_group_id']);


        //2. 返回平台资源
        $resourceServer = new LocalInfo();
        $server_resource = $resourceServer->disk();

        //3. 返回当前用户组菜单
        $PermissionsService = new PermissionsService();

        $menuList = $PermissionsService->menuList($this->loginUser['id']);

        $return = [
            'token' => $this->toekn,
            'show_name' => $this->loginUser['show_name'],
            'level' => $this->loginUser['user_group_level'],
            'user_id' => $this->loginUser['id'],
            'user_group_id' => $this->loginUser['user_group_id'],
            'expire_msg' => $authStatus['expire_msg'],
            'expire_status' => $authStatus['expire_status'],
            'menu' => $menuList,
            'server_resource' => $server_resource
        ];

        return $return;
    }

    /**
     *  加入用户日志
     */
    function __destruct()
    {
        if(!empty($this->loginUser)){

            global $errCode;
            global $errMsg;

            $content = '系统登录';
            $status = 1;
            if($errCode != $this->CODE_SUCCESS){
                $content.= ' [ 失败原因：'.$errMsg.']';
                $status = 0;
            }

            //1. 查询ip对应的地址address
            $addressR = $_SERVER['DOCUMENT_ROOT'].'/static/IP/qqzeng.dat';
            if(!file_exists($addressR))
            {
                return true;
            }
            $ipServer = new Ip($addressR);
            $ipInfo = $ipServer->getlocation($_SERVER['REMOTE_ADDR']);
            $address = $ipInfo['country'].$ipInfo['province'].$ipInfo['city'].$ipInfo['area'];

            db('server_option_history')->insert([
                'type' => 1,
                'content' => $content,
                'ip' => $this->loginIp,
                'address' => $address,
                'user_id' => $this->loginUser['id'],
                'ctime' => time(),
                'status' => $status,
            ]);
        }

        if ($this->nowFailedCount < $this->maxKeepLoginFailedCount && !empty($this->loginUser))
        {
            db('ServerLoginLog')->insert([
                'user_id' => $this->loginUser['id'],
                'login_ip' => $this->loginIp,
                'login_time' => $this->loginTime,
                'year' => $this->year,
                'month' => $this->month,
                'day' => $this->day,
                'failed' => $this->failed,
            ]);
        }
    }
}